#include "cybertron/network/CybertronSyncConn.hpp"
#include "cybertron/core/Log.hpp"
#include "cybertron/network/Message.hpp"

CYBERTRON_BEGIN

CybertronSyncConn::CybertronSyncConn()
{
	mpClient = std::make_shared<SocketTcpClientSync>();
	mIp.clear();
	mPort = 0;
}

CybertronSyncConn::~CybertronSyncConn()
{

}

bool CybertronSyncConn::connect(const std::string& ip, int port)
{
	mIp = ip;
	mPort = port;
	if (!mpClient->connect(mIp, mPort))
	{
		logError("CybertronSyncConn connect failed %s:%d", mIp.c_str(), mPort);
		return false;
	}
	return true;
}

CybertronSyncConn::QueryResult CybertronSyncConn::query(std::uint32_t type, google::protobuf::MessageLite& protoMsg)
{
	NodeCommon::FromAnyRequestData request;
	request.add_datatypes(type);
	if (!mpClient->send(NodeCommon::EFromAnyRequestData, request))
	{
		logError("CybertronSyncConn query disconnected %s:%d", mIp.c_str(), mPort);
		return QUERY_DISCONNECT;
	}
	Message replyMsg;
	if (!mpClient->receive(replyMsg, /*TimeoutMS*/100))
	{
		logError("CybertronSyncConn query timeout %s:%d", mIp.c_str(), mPort);
		return QUERY_TIMEOUT;
	}
	if (!replyMsg.toProtobuf(protoMsg))
	{
		logError("CybertronSyncConn query msg wrong %s:%d", mIp.c_str(), mPort);
		return QUERY_UNEXPECTED_REPLY;
	}
	return QUERY_SUCCESS;
}

CybertronSyncConn::QueryResult CybertronSyncConn::query(const Message& requestMsg, google::protobuf::MessageLite& protoMsg)
{
    if (!mpClient->send(requestMsg))
    {
        logError("CybertronSyncConn query disconnected %s:%d", mIp.c_str(), mPort);
        return QUERY_DISCONNECT;
    }
    Message replyMsg;
    if (!mpClient->receive(replyMsg, /*TimeoutMS*/10000))
    {
        logError("CybertronSyncConn query timeout %s:%d", mIp.c_str(), mPort);
        return QUERY_TIMEOUT;
    }
    if (!replyMsg.toProtobuf(protoMsg))
    {
        logError("CybertronSyncConn query msg wrong %s:%d", mIp.c_str(), mPort);
        return QUERY_UNEXPECTED_REPLY;
    }
    return QUERY_SUCCESS;
}

CybertronSyncConn::SendResult CybertronSyncConn::send(std::uint16_t msgId, google::protobuf::MessageLite& protoMsg)
{
	if (!mpClient->send(msgId, protoMsg))
	{
		logError("CybertronSyncConn send disconnected %s:%d", mIp.c_str(), mPort);
		return SEND_DISCONNECT;
	}
	return SEND_SUCCESS;
}

CybertronSyncConn::SendResult CybertronSyncConn::send(Message& msg) {
	if (!mpClient->send(msg))
	{
		logError("CybertronSyncConn send disconnected %s:%d", mIp.c_str(), mPort);
		return SEND_DISCONNECT;
	}
	return SEND_SUCCESS;
}


void CybertronSyncConn::release()
{
	mpClient->close();
}

CYBERTRON_END